When a company rolls out GitHub Copilot, developers start using it in different ways. Some rely on code completions, others use chat to understand unfamiliar code, and some use agent features to handle larger development tasks.
For an engineering manager, the difficult part is understanding whether Copilot is being adopted across the team. For developers, the concern is different: does measuring adoption mean someone needs to collect their prompts, generated responses, or coding conversations?
Not necessarily.
GitHub provides Copilot usage metrics through its dashboards and APIs. These reports can help organizations understand active usage, feature adoption, and changes over time without building an internal system that stores the actual text of developer conversations.
The distinction matters. Measuring how often a feature is used is different from recording what a developer asks it to do. A well-designed reporting system collects only the information needed to answer the organization's questions.
Understanding GitHub Copilot Usage Metrics
Before building a reporting system, it is important to understand which metrics are available and what they actually tell you.
GitHub's Copilot usage metrics include information about user activity, feature usage, and code generation. Depending on the report, data may be available at an organization, enterprise, repository, or individual-user level.
Some reports contain aggregated totals, while others identify individual accounts. The fields available depend on the report type.
The following metrics are useful when evaluating adoption.
| Metric | What it measures | How to use it |
|---|
| Assigned users | Developers with Copilot access | Compare licenses with actual usage |
| Active users | Users who meet the report's activity definition | Measure adoption during a reporting period |
| Feature usage | Activity involving supported Copilot features | Understand which capabilities developers use |
| Code generation metrics | Available measures of suggested, added, or deleted code | Understand code-generation activity |
| Adoption trends | Changes in usage across reporting periods | Evaluate whether adoption is growing or declining |
These metrics should not be treated as interchangeable. For example, a developer may use Copilot Chat without using inline code completion during the same period.
Similarly, code-generation counts do not establish that the generated code was correct, secure, or accepted into production.
For an initial adoption report, active users and feature-level activity are usually more useful than trying to measure every available field.
Retrieving Copilot Usage Data Through the API
An organization can start with GitHub's built-in dashboard. When the team needs scheduled reports or a custom dashboard, the usage metrics API provides a way to retrieve the required data.
Before making API requests, check three things:
- Copilot usage metrics must be enabled under the applicable enterprise policy.
- The account or application making the request must have the required metrics permissions.
- The selected endpoint must match the required reporting scope.
For example, an organization-level daily report can be requested using the following API endpoint.
GET /orgs/{org}/copilot/metrics/reports/organization-1-day?day=2026-10-12
The request uses the organization name and the reporting date. The API returns report information, including a temporary download link when a report is available.
A typical request using curl looks like this:
curl --request GET \
--url "https://api.github.com/orgs/ORG_NAME/copilot/metrics/reports/organization-1-day?day=2026-10-12" \
--header "Accept: application/vnd.github+json" \
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
--header "X-GitHub-Api-Version: 2026-03-10"
Replace ORG_NAME with the organization's name. Set GITHUB_TOKEN to a securely stored token with the appropriate organization Copilot metrics read permission.
The API version shown is an example of a supported versioned request. Confirm the version used by your integration before deploying it.
One detail is easy to miss: this endpoint does not necessarily return all the usage records directly in the response body. It can return a temporary download URL for a report. Your application must handle the response and download the report before processing its contents.
These URLs expire, so download the report within the permitted period. Avoid writing the signed URL to application logs because it may grant temporary access to the report.
Processing Usage Data Without Storing Conversations
Once the report has been downloaded, the next step is to extract only the metrics required by the reporting process.
Copilot usage exports can use newline-delimited JSON, commonly called NDJSON. In this format, each line is a separate JSON object rather than one large JSON array.
For example, a simplified internal representation might look like this:
{"active_users": 72, "reporting_period": "2026-10-12"}
{"active_users": 75, "reporting_period": "2026-10-13"}
These records are illustrative examples for explaining the format, not actual GitHub API responses.
A Python script can process such a file and produce a simple adoption summary.
import json
from pathlib import Path
report_path = Path("usage-report.ndjson")
daily_totals = []
with report_path.open("r", encoding="utf-8") as report:
for line in report:
if not line.strip():
continue
record = json.loads(line)
daily_totals.append({
"reporting_period": record["reporting_period"],
"active_users": record["active_users"]
})
for item in daily_totals:
print(
f'{item["reporting_period"]}: '
f'{item["active_users"]} active users'
)
This example expects the simplified fields shown above. A production implementation must map the actual fields returned by the selected GitHub report.
The important design decision is that the processing code extracts the required counts and dates instead of copying the entire source record into a separate database.
If the reporting system does not need prompt text or generated responses, do not add fields for that content or create another collection mechanism to capture it.
Filtering fields during processing reduces unnecessary data retention, but it does not prove that the original report contains no other identifying information. Check the report schema and handle the source file accordingly.
Calculating Adoption Rates Correctly
The adoption rate is calculated by dividing the number of active users by the total number of assigned users and multiplying the result by 100.
For example, if an organization has 100 assigned Copilot users and 72 active users, the adoption rate is:
Adoption Rate = (Active Users / Assigned Users) * 100
= (72 / 100) * 100
= 72%
A Python function can calculate the rate and handle invalid input:
def calculate_adoption_rate(
assigned_users: int,
active_users: int
) -> float:
if assigned_users < 0 or active_users < 0:
raise ValueError("User counts cannot be negative.")
if active_users > assigned_users:
raise ValueError(
"Active users cannot exceed assigned users."
)
if assigned_users == 0:
return 0.0
return (active_users / assigned_users) * 100
rate = calculate_adoption_rate(100, 72)
print(f"Adoption rate: {rate:.1f}%")
Output:
Adoption rate: 72.0%
The function validates the input before performing the calculation. It also handles the case where no users have been assigned a license, preventing division by zero.
A simple Python function can calculate the rate safely:
def calculate_adoption_rate(
assigned_users: int,
active_users: int
) -> float:
if assigned_users < 0 or active_users < 0:
raise ValueError("User counts cannot be negative.")
if active_users > assigned_users:
raise ValueError(
"Active users cannot exceed assigned users "
"for this calculation."
)
if assigned_users == 0:
return 0.0
return active_users / assigned_users * 100
rate = calculate_adoption_rate(100, 72)
print(f"Adoption rate: {rate:.1f}%")
This produces an adoption rate of 72.0%.
The validation assumes that both counts refer to the same population and reporting period. If the reports use different scopes or definitions, the result may be misleading even when the arithmetic is correct.
For production reporting, also decide how to represent an organization with no assigned users. Returning zero is convenient for a simple dashboard, but some reports should display "Not applicable" instead because no adoption rate can be calculated.
Designing a Privacy-Conscious Reporting Pipeline
A reporting pipeline should separate data retrieval, processing, and storage.
A straightforward design has four stages:
- Retrieve: Request the required usage report using an authorized identity.
- Process: Parse the downloaded report and extract approved metrics.
- Aggregate: Calculate daily totals, adoption rates, and feature-level summaries.
- Store: Save only the fields required for the dashboard and historical comparisons.
For example, a reporting database might store the reporting date, organization identifier, active-user count, assigned-user count, and calculated adoption rate.
It should not automatically store every raw report simply because the API makes it available.
Protect the reporting credentials
Keep the API token in a secret manager or protected CI/CD secret store. Do not place it directly in source code or commit it to the repository.
Use the minimum permissions required for the selected report. A reporting job should not receive administrative permissions when read-only metrics access is sufficient.
Limit access to individual-level reports
Organization-wide totals may be enough for routine management reviews. Individual-level reports should be restricted to authorized personnel with a defined need.
Also, do not assume that removing prompt text makes a report anonymous. Usernames, account identifiers, team membership, and detailed activity patterns may still identify developers.
Define a retention policy
Temporary downloads should be removed after processing when they are no longer required. Retain aggregated results for as long as the organization has a legitimate reporting need.
If raw exports must be retained for auditing, document the reason, restrict access, and define when those files will be deleted.
Advantages and Disadvantages
Advantages
Less sensitive data in internal systems: Teams can focus on usage counts and summaries rather than creating a separate store for developer conversations.
Consistent reporting: Scheduled API exports allow teams to compare activity across defined reporting periods.
Better visibility into adoption: Managers can distinguish between assigned licenses and actual usage.
Flexible reporting: Aggregated metrics can be used in existing business intelligence tools without requiring a separate application for every report.
Disadvantages
Usage metrics have limitations: Activity counts cannot independently measure code quality, productivity, or developer satisfaction.
API access requires configuration: Permissions, reporting policies, and API availability must be checked before automation can run.
Data processing still needs care: Raw reports may contain identifying fields even when they do not contain prompt or response text.
Metrics can be misinterpreted: Different report types and reporting periods may produce totals that cannot be compared directly.
Common Mistakes and Troubleshooting
| Problem | What to check |
|---|
The API returns 403 Forbidden | Verify the metrics policy and the token's required permissions |
The API returns 204 No Content | Check whether data is available for the requested date and endpoint |
| The report download fails | Confirm that the temporary download link has not expired |
| The parser fails on the report | Check whether the file is NDJSON or another JSON structure |
| Adoption percentages look incorrect | Verify that assigned and active user counts have the same scope and period |
| The reporting database contains unnecessary fields | Review the extraction logic and retain only approved metrics |
A common mistake is assuming that a successful API request means the reporting process is complete. The download, parsing, validation, aggregation, and storage stages can each fail independently.
Log the reporting date, endpoint category, processing status, and error details where appropriate. Avoid logging access tokens, temporary signed URLs, or raw report contents unnecessarily.
Best Practices for Production Use
- Start with the built-in dashboard before building a custom integration.
- Select metrics that answer a specific adoption question.
- Use a dedicated application identity with read-only metrics permissions where supported.
- Validate report schemas before relying on particular fields.
- Keep API credentials and temporary download links out of logs.
- Store aggregated results instead of retaining raw exports indefinitely.
- Explain to developers what is measured and who can access the reports.
- Never use Copilot activity counts alone as a measure of an individual's performance.
Summary
GitHub Copilot adoption can be measured without building a system that collects the prompts developers enter or the responses Copilot generates. GitHub's usage dashboards and APIs provide a practical starting point for understanding active usage, feature adoption, and changes over time.
The technical challenge is not simply retrieving the metrics. It is processing the reports correctly, protecting access credentials, distinguishing aggregate data from individual-level information, and storing only what the organization needs.
For most engineering teams, a small reporting pipeline that extracts approved metrics and retains aggregated results is a better starting point than collecting every available field. It provides useful adoption information while reducing unnecessary handling of developer activity data.
Join the conversation! Your thoughts help the community grow.