Copilot AIクレジット可視化入門——usage metrics APIをFirestoreに蓄積する
GitHub Copilot usage metrics APIに追加されたai_credits_usedを題材に、Next.js + Firestoreで日次のAI利用量を見える化する実装を解説します。

はじめに
GitHub Copilotをチームで使っていて、こんな確認に時間がかかっていませんか?
| 確認したいこと | よくある困りごと |
|---|---|
| 誰がどれくらいAI機能を使っているか | 管理画面だけでは日次の比較がしづらい |
| チームごとの利用傾向 | メンバーの所属情報と結合する必要がある |
| 予算超過の兆候 | 請求が確定する前に変化を見たい |
2026年6月19日、GitHubはCopilot usage metrics APIのユーザー単位レポートに ai_credits_used を追加したと発表しました。これは各ユーザーが1日に消費したAIクレジット数を示すフィールドです。
本記事では、架空の営業支援SaaS「LeadPort」を題材に、GitHub CopilotのAIクレジット利用量をGitHub Actionsで日次取得し、Firestoreへ蓄積してNext.jsの管理画面で確認する流れを解説します。
何が変わったのか
GitHubの発表によると、ai_credits_used はユーザーレベルの users-1-day と users-28-day レポートで利用できます。対象はOrganizationとEnterpriseの両方です。
重要なのは、この値が「請求書の明細そのもの」ではない点です。GitHubは ai_credits_used を利用分析のためのメトリクスとして扱い、請求確認はusage-based billing APIや請求画面を見るよう説明しています。また、現時点では機能別、モデル別、利用面別には分解されません。
LeadPortでは、請求確定後に慌てるのではなく、毎朝の定点観測で「どのチームの利用が伸びているか」「オンボーディング対象が使えているか」を見ます。
取得に使う公式エンドポイント
Organization単位で日次のユーザー利用量を取る場合、GitHub Docsに記載されているエンドポイントは次です。
GET /orgs/{org}/copilot/metrics/reports/users-1-day?day=YYYY-MM-DD
Enterprise単位では次を使います。
GET /enterprises/{enterprise}/copilot/metrics/reports/users-1-day?day=YYYY-MM-DD
このAPIは、ユーザー行を直接JSONで返すのではなく、期限付きの download_links を返します。リンク先のNDJSONをさらにダウンロードして、1行ずつ処理する設計です。
チーム別に集計したい場合は、日次の user-teams-1-day レポートと users-1-day レポートを user_id と day で結合します。GitHub Docsでは、28日分のユーザーレポートを単日のチーム所属レポートに結合しないよう注意されています。チーム異動があると、過去の利用を現在のチームへ誤って寄せてしまうためです。
ハンズオン1: Firestoreの保存形を決める
まず、日次ユーザー行をそのまま近い形で保存します。最初から複雑な集計ドキュメントだけにすると、あとから指標が増えたときに再計算しづらくなります。
import { FieldValue, type Firestore } from "firebase-admin/firestore";
type CopilotUserUsageRow = {
day: string;
organization_id?: number;
enterprise_id?: number;
user_id: number;
user_login: string;
ai_credits_used?: number;
};
export async function saveCopilotUsageRows(
db: Firestore,
rows: CopilotUserUsageRow[],
) {
const batch = db.batch();
for (const row of rows) {
const id = `${row.day}_${row.user_id}`;
const ref = db.collection("copilotDailyUsage").doc(id);
batch.set(
ref,
{
...row,
aiCreditsUsed: row.ai_credits_used ?? 0,
syncedAt: FieldValue.serverTimestamp(),
},
{ merge: true },
);
}
await batch.commit();
}
ai_credits_used はAPI側のフィールド名として保持しつつ、アプリ内では aiCreditsUsed に寄せています。LeadPortでは、元データと表示用データの両方を残し、仕様変更時に追跡しやすくします。
ハンズオン2: GitHub APIからNDJSONを取得する
次に、GitHub Actionsから実行する同期スクリプトを作ります。ここではOrganization単位の例に絞ります。
type ReportResponse = {
download_links: string[];
report_day?: string;
};
async function fetchReportLinks(org: string, day: string, token: string) {
const url = new URL(
`https://api.github.com/orgs/${org}/copilot/metrics/reports/users-1-day`,
);
url.searchParams.set("day", day);
const response = await fetch(url, {
headers: {
Accept: "application/vnd.github+json",
Authorization: `Bearer ${token}`,
"X-GitHub-Api-Version": "2026-03-10",
},
});
if (response.status === 204) {
return [];
}
if (!response.ok) {
throw new Error(`GitHub API failed: ${response.status}`);
}
const body = (await response.json()) as ReportResponse;
return body.download_links;
}
async function downloadNdjson<T>(url: string): Promise<T[]> {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Report download failed: ${response.status}`);
}
const text = await response.text();
return text
.split("\n")
.filter(Boolean)
.map((line) => JSON.parse(line) as T);
}
必要な権限は、Organizationでは「Organization Copilot metrics」のread権限です。従来の個人アクセストークンを安易に共有するより、GitHub Appやfine-grained personal access tokenで用途を絞るほうが運用しやすいです。
ハンズオン3: GitHub Actionsで日次同期する
LeadPortでは、毎朝9時JSTに前日分を同期します。GitHub ActionsのcronはUTCなので、0 0 * * * がJSTの9時です。
name: Sync Copilot Usage
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
inputs:
day:
description: "YYYY-MM-DD"
required: false
type: string
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "yarn"
- run: yarn install --frozen-lockfile
- name: Sync usage
env:
GITHUB_COPILOT_METRICS_TOKEN: ${{ secrets.COPILOT_METRICS_TOKEN }}
GITHUB_ORG: ${{ vars.GITHUB_ORG }}
TARGET_DAY: ${{ github.event.inputs.day }}
FIREBASE_SERVICE_ACCOUNT_JSON: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON }}
run: node scripts/sync-copilot-usage.mjs
当日分はまだ処理されていない可能性があります。スクリプト側では TARGET_DAY が空なら前日を選び、204が返った場合は失敗ではなく「まだデータなし」としてログに残す運用にします。
Next.js管理画面で見る指標
Firestoreに蓄積したら、Next.js App RouterのServer Componentで日次集計を表示できます。
import { getFirestore } from "firebase-admin/firestore";
type DailyCopilotSummary = {
day: string;
activeUsers: number;
totalAiCredits: number;
};
export async function getDailyCopilotSummary(
day: string,
): Promise<DailyCopilotSummary> {
const db = getFirestore();
const snapshot = await db
.collection("copilotDailyUsage")
.where("day", "==", day)
.get();
let totalAiCredits = 0;
let activeUsers = 0;
snapshot.forEach((doc) => {
const data = doc.data() as { aiCreditsUsed?: number };
const credits = data.aiCreditsUsed ?? 0;
totalAiCredits += credits;
if (credits > 0) activeUsers += 1;
});
return { day, activeUsers, totalAiCredits };
}
表示では、個人をランキングするよりもチーム単位の傾向を優先します。AI利用量は成果の代理指標ではありません。LeadPortでは、PR作成数、レビュー待ち時間、問い合わせ対応時間などの業務指標と並べ、使いすぎの検出だけでなく、活用できていないチームの支援にも使います。
運用チェックリスト
| 項目 | 判断基準 |
|---|---|
| 権限 | Copilot metricsのreadに限定する |
| 保存範囲 | 原則として日次集計とGitHub loginだけにする |
| 取り扱い | 個人評価ではなくチーム支援・予算管理に使う |
| 請求確認 | ai_credits_used だけで請求額を断定しない |
| 集計 | チーム別は日次user-teamsと日次usersを結合する |
特に最後の2つは重要です。ai_credits_used は利用傾向を早く見るためのフィールドであり、モデル別の料金や追加課金額を確定するものではありません。請求の正確な確認には、GitHubのbilling系APIや管理画面を併用します。
参考リンク
- AI credits consumed per user now in the Copilot usage metrics API
- REST API endpoints for Copilot usage metrics
- Team-level Copilot usage metrics
- Usage-based billing for organizations and enterprises
まとめ
ai_credits_used の追加により、CopilotのAI利用量をユーザー単位の日次メトリクスとして扱いやすくなりました。Next.js + Firestoreの構成なら、GitHub Actionsで毎日NDJSONを取得し、管理画面に小さく可視化できます。
最初は「前日分の合計」「アクティブユーザー数」「チーム別の増減」だけで十分です。請求額を断定するダッシュボードではなく、予算と活用状況を早めに把握する運用メーターとして育てていくのが現実的です。