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.

MetricWhat it measuresHow to use it
Assigned usersDevelopers with Copilot accessCompare licenses with actual usage
Active usersUsers who meet the report's activity definitionMeasure adoption during a reporting period
Feature usageActivity involving supported Copilot featuresUnderstand which capabilities developers use
Code generation metricsAvailable measures of suggested, added, or deleted codeUnderstand code-generation activity
Adoption trendsChanges in usage across reporting periodsEvaluate 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:

  1. Copilot usage metrics must be enabled under the applicable enterprise policy.
  2. The account or application making the request must have the required metrics permissions.
  3. The selected endpoint must match the required reporting scope.

For example, an organization-level daily report can be requested using the following API endpoint.

Code
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:

Bash
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:

JSON
{"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.

Python
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:

Code
Adoption Rate = (Active Users / Assigned Users) * 100
              = (72 / 100) * 100
              = 72%

A Python function can calculate the rate and handle invalid input:

Python
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:

Code
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:

Python
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:

  1. Retrieve: Request the required usage report using an authorized identity.
  2. Process: Parse the downloaded report and extract approved metrics.
  3. Aggregate: Calculate daily totals, adoption rates, and feature-level summaries.
  4. 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

ProblemWhat to check
The API returns 403 ForbiddenVerify the metrics policy and the token's required permissions
The API returns 204 No ContentCheck whether data is available for the requested date and endpoint
The report download failsConfirm that the temporary download link has not expired
The parser fails on the reportCheck whether the file is NDJSON or another JSON structure
Adoption percentages look incorrectVerify that assigned and active user counts have the same scope and period
The reporting database contains unnecessary fieldsReview 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.